#pragma once

#include <functional>
#include <sys/wait.h>
#include "Sock.hpp"
#include "protocol.hpp"
#include "log.hpp"
#include "err.hpp"
#include "Util.hpp"

namespace server
{
    static const int defaultport = 8080;

    using func_t = std::function<bool(const HttpRequest &, HttpResponse &)>;

    class httpServer
    {
    public:
        httpServer(const func_t func, const uint16_t &port = defaultport)
            : _func(func), _port(port)
        {
        }

        void initServer()
        {
            _sock.Socket();
            _sock.Bind(_port);
            _sock.Listen();
        }

        void handlerEvent(int sock)
        {
            // 1. 读到完整的http请求
            // 2. 反序列化
            // 3. httprequst, httpresponse, _func(req, resp)
            // 4. resp序列化
            // 5. send
            char buffer[4096];
            HttpRequest req;
            HttpResponse resp;
            size_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                req.inbuffer = buffer;
                req.parse();
                _func(req, resp); // req -> resp
                send(sock, resp.outbuffer.c_str(), resp.outbuffer.size(), 0);
            }
        }

        void start()
        {
            for (;;)
            {
                int sock = _sock.Accept();
                if (sock < 0)
                    continue;

                pid_t id = fork();
                if (id == 0)
                {
                    _sock.Close();
                    if (fork() > 0)
                        exit(0);
                    handlerEvent(sock);
                    close(sock);
                    exit(0);
                }
                close(sock);

                waitpid(id, nullptr, 0);
            }
        }

        ~httpServer()
        {
        }

    private:
        Sock _sock;
        uint16_t _port;
        func_t _func;
    };
}